Skip to content

fix: validate duplicate language configurations in CHECKCFG#1376

Draft
joaodinissf wants to merge 4 commits into
dsldevkit:masterfrom
joaodinissf:fix/checkcfg-duplicate-language-validation
Draft

fix: validate duplicate language configurations in CHECKCFG#1376
joaodinissf wants to merge 4 commits into
dsldevkit:masterfrom
joaodinissf:fix/checkcfg-duplicate-language-validation

Conversation

@joaodinissf

@joaodinissf joaodinissf commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Adds an error-severity validation that flags duplicate language configurations in a CHECKCFG file.

The grammar accepts multiple for <Language> { ... } blocks in one configuration, with no defined semantics for how duplicates combine. CheckCfgValidator.checkConfiguredLanguageUnique now reports an error on each ConfiguredLanguageValidator that shares a language name with another, mirroring the existing catalog/check/parameter uniqueness validators and reusing the getDuplicates() helper. Covered by CheckCfgTest.testDuplicateLanguageNotOk.

Validation only, no quick-fix: a quick-fix would have to merge the duplicate blocks, which cannot preserve generated output. Language-level parameters are inherited by inner catalogs/checks and the generator resolves them first-wins per section, so collapsing two blocks into one silently changes which value inner catalogs inherit. The correct resolution depends on author intent, so the error guides the user to resolve duplicates manually.

Closes #103

🤖 Generated with Claude Code

@joaodinissf joaodinissf force-pushed the fix/checkcfg-duplicate-language-validation branch from 133312f to c89159f Compare May 30, 2026 10:58
@joaodinissf joaodinissf marked this pull request as draft May 30, 2026 17:14
@joaodinissf joaodinissf changed the title fix: validate and quick-fix duplicate languages in CHECKCFG (closes #103) fix: validate and quick-fix duplicate languages in CHECKCFG May 30, 2026
The CHECKCFG grammar accepts multiple `for <Language> { ... }` blocks in one
configuration. Nothing validated against the same language appearing twice, so
duplicate blocks were silently allowed with no defined semantics for how their
configurations combine.

Add an error-severity validation plus a quick-fix:

  - checkConfiguredLanguageUnique on CheckConfiguration reports an error on each
    duplicate ConfiguredLanguageValidator sharing a language name. Mirrors the
    existing catalog/check/parameter uniqueness validators and reuses the
    getDuplicates() helper. Simpler than the catalog case: getLanguage() returns
    a String, so no proxy check is needed.
  - removeDuplicateLanguageConfiguration quick-fix merges every later block's
    parameter and catalog configurations into the first occurrence and deletes
    the duplicates.

Tests live in CheckCfgTest; the surrounding checkcfg.core.test validation files
are migrated Xtend -> Java to add them.

This revives the approach from the long-closed dsldevkit#104 (validation + merge
quick-fix), reimplemented against the current Java validator/quick-fix code,
which was renamed and migrated off Xtend since 2018.

Closes dsldevkit#103

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@joaodinissf joaodinissf marked this pull request as ready for review June 12, 2026 20:47
@joaodinissf joaodinissf force-pushed the fix/checkcfg-duplicate-language-validation branch from c89159f to 4bd5ca1 Compare June 12, 2026 20:47
@joaodinissf joaodinissf requested a review from rubenporras June 12, 2026 20:47
@joaodinissf joaodinissf enabled auto-merge (rebase) June 12, 2026 20:47
@joaodinissf joaodinissf marked this pull request as draft June 12, 2026 21:07
auto-merge was automatically disabled June 12, 2026 21:07

Pull request was converted to draft

@joaodinissf joaodinissf removed the request for review from rubenporras June 12, 2026 21:07
…ration

Extracts the merge logic from the UI quickfix provider's anonymous
ISemanticModification into CheckCfgQuickfixes in checkcfg.core, leaving the
provider a thin @fix wrapper. The model transformation is now exercisable
without an editor or workbench, and CheckCfgQuickfixesTest covers six
scenarios (catalog merge, parameter merge, 3+ occurrences, language
selectivity, invocation-independence, empty duplicate) against parsed models
in checkcfg.core.test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@joaodinissf joaodinissf force-pushed the fix/checkcfg-duplicate-language-validation branch 2 times, most recently from fdcf350 to 01559a7 Compare June 14, 2026 09:36
joaodinissf and others added 2 commits June 14, 2026 11:39
To the reviewer:

Thank you — your three findings on the dedup-aware merge were all correct,
and this commit is the considered response. The short version: I implemented
the deduplication direction your findings pointed at, it made things worse, so
I reverted it and kept the original order-preserving concatenation, now with
its contract and limitations documented explicitly. Reasoning in full:

Findings 1 and 2 (same-catalog merge dropped catalog-level parameters;
duplicate-check merge dropped the earlier check's parameters). You were right
and these were genuine data loss. Crucially they existed ONLY in the
dedup-aware merge I had added, not in the original concatenation: ConfiguredCatalog
and ConfiguredCheck both extend ConfigurableSection, so each carries its own
parameter configurations, and collapsing same-named catalogs/checks silently
dropped them. I have reverted that dedup commit in full. With no deduplication
nothing is dropped, so findings 1 and 2 no longer apply to the code under review.

Why concatenation rather than a corrected, deeper dedup. The properties
generator is last-wins (it puts configurations into a Properties map in order,
so a later definition overrides an earlier one). Order-preserving concatenation
relocates every entry into one block in its original order, which reproduces the
exact generated output of the original duplicate blocks — it is behaviour-
preserving. Your findings demonstrated the opposite for dedup: any scheme that
removes the resulting language-scoped duplicates ends up dropping scoped
parameters the generator would have emitted. A fully faithful dedup would have
to replicate the generator's whole inheritance resolution inside the quick-fix,
which is disproportionate and a large new bug surface. So the safe choice is to
move entries without rewriting them.

Finding 3 (language-level parameter rescoping). Agreed, and note it is inherent
to collapsing two blocks into one — it is present in any merge, including the
original, not something dedup introduced. In the common case it is harmless; in
the rare case where the duplicate blocks carry different block-level inherited
parameters it genuinely cannot be represented in a single block. We accept this:
the quick-fix resolves the duplicate-LANGUAGE error the issue asks for; it does
not claim to resolve every downstream inheritance conflict, whose correct
resolution depends on user intent the tool cannot infer.

Residual unvalidated duplicates (your earlier rounds). The concatenation can
leave language-scoped duplicate catalogs/parameters that no validator flags.
That validation gap is pre-existing and independent of this change: language-
scoped catalog/parameter uniqueness is simply not validated anywhere today, and
the originating issue (dsldevkit#103) asks only for duplicate-language validation plus a
merge quick-fix, both of which this PR delivers. Adding language-scoped
uniqueness validation is worthwhile but is a separate concern, tracked as a
follow-up rather than expanding this PR. Until then the residual duplicates are
benign at generation (same last-wins outcome).

Coverage gap (no @Fix-execution test). Accepted. As you verified, the provider
cast is safe by construction — the error is reported on a ConfiguredLanguageValidator
source — and the model transformation itself is covered by the core tests.

This commit changes only the Javadoc of mergeDuplicateLanguageConfigurations to
record the order-preserving contract, the behaviour-preservation rationale, and
the documented scope boundary, so the intent is explicit for future readers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
To the reviewer:

Your fourth-round finding stands and I have verified it directly: the
generator collects inherited parameters by walking parent ConfigurableSections
and taking the first occurrence of each name per section (first-wins). So
collapsing two duplicate language blocks into one — which any merge must do —
moves both blocks' language-level parameters into a single section, and the
inner catalogs silently inherit the first value instead of their original
per-block value. That is a real generated-output change, and no consolidating
merge can avoid it without materializing the generator's full inheritance
resolution down into every catalog/check scope, which is disproportionate.

This is not specific to my implementation: the rescoping (and the unvalidated
language-scoped duplicates from the earlier rounds) is intrinsic to the
"merge duplicate language blocks" idea as originally conceived in dsldevkit#104 back in
2018; only the dedup data-loss from fdcf350 was mine, and that was reverted.
The merge quick-fix was never safely automatable.

So this commit removes the quick-fix entirely and keeps the part that is
correct and valuable: the error-severity validation that flags duplicate
language configurations (checkConfiguredLanguageUnique, IssueCodes.
DUPLICATE_LANGUAGE_CONFIGURATION, and its test). The correct resolution of a
duplicate depends on which inherited value the author intended per block —
intent a quick-fix cannot infer and would silently guess wrong — so manual
resolution guided by the error is the right behaviour.

Removed: the @fix removeDuplicateLanguageConfiguration in CheckCfgQuickfixProvider,
the UI-independent CheckCfgQuickfixes core class and its tests, the
checkcfg.quickfix package export, the suite entry, and the now-unused UI
message keys. Issue dsldevkit#103 asked for "validation and a quick-fix"; we deliver the
validation now, and the merge quick-fix is dropped as unsound. Adding
language-scoped catalog/parameter uniqueness validation (a pre-existing gap) is
left as a separate follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@joaodinissf joaodinissf changed the title fix: validate and quick-fix duplicate languages in CHECKCFG fix: validate duplicate language configurations in CHECKCFG Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CHECKCFG allows duplicate languages

1 participant